﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.Infra.Service.Common;
using PSE.ProcessManager.Client.Process;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.UI.Common;
using PSE.ProcessManager.Entity;

namespace Sinacor.Infra.Core.ProcessManager.Client.Service
{
    public abstract class BaseCommunicationProcess<T> : Sinacor.Infra.Service.Common.BaseCommunication, IBaseCommunicationProcess
            where T : SinacorBaseProcessClient, new()
    {
        protected T Process { get; private set; }

        public BaseCommunicationProcess(string loginName, string password, int companyId)
            : this(loginName, password, companyId, null, null, null)
        {
        }

        public BaseCommunicationProcess(string loginName, string password, int companyId, int? sessionId, string tokenId, bool? sessionExpires)
            : base(loginName, password, companyId, sessionId, tokenId, sessionExpires)
        {
            this.Process = new T();
            this.Process.SetUserCredentials(this.LoginName, this.Password, this.CompanyId);

            this.Process.Connected += new EventHandler(Process_Connected);
            this.Process.Initialized += new EventHandler(Process_Initialized);
            this.Process.ProcessStatusReceived += new EventHandler<PSE.ProcessManager.Client.Process.ProcessStatusEventArgs>(Process_ProcessStatusReceived);
            this.Process.ProcessThrowAnException += new EventHandler<PSE.ProcessManager.Client.Process.ExceptionEventArgs>(Process_ProcessThrowAnException);
            this.Process.Finalized += new EventHandler(Process_Finalized);
            this.Process.Aborted += new EventHandler(Process_Aborted);
            this.Process.Disconnected += new EventHandler(Process_Disconnected);
        }

        #region IsProcessRunning
        public bool IsProcessRunning()
        {
            try
            {
                return this.Process.IsProcessRunning();
            }
            catch (Exception ex)
            {
                HandleFault(ex);
            }
            return false;
        }
        #endregion

        #region Connect
        public bool IsConnected { get; private set; }

        public void Connect()
        {
            try
            {
                this.Process.BeginConnect();
            }
            catch (Exception ex)
            {
                HandleFault(ex);
            }
        }

        public event EventHandler Connected;

        protected virtual void OnConnected(EventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            this.IsConnected = true;

            if (Connected != null)
                Connected(this, e);
        }

        void Process_Connected(object sender, EventArgs e)
        {
            this.OnConnected(e);
        }
        #endregion

        #region Initialize
        public event EventHandler Initialized;

        protected virtual void OnInitialized(EventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            if (Initialized != null)
                Initialized(this, e);
        }

        void Process_Initialized(object sender, EventArgs e)
        {
            this.OnInitialized(e);
        }
        #endregion

        #region ProcessStatusReceived
        public event EventHandler<ProcessStatusEventArgs> ProcessStatusReceived;

        protected virtual void OnProcessStatusReceived(ProcessStatusEventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            if (ProcessStatusReceived != null)
                ProcessStatusReceived(this, e);
        }

        void Process_ProcessStatusReceived(object sender, ProcessStatusEventArgs e)
        {
            this.OnProcessStatusReceived(e);
        }
        #endregion

        #region ProcessThrowAnException
        void Process_ProcessThrowAnException(object sender, PSE.ProcessManager.Client.Process.ExceptionEventArgs e)
        {
            HandleFault(e.Ex, false);
        }
        #endregion

        #region Finalize
        public event EventHandler Finalized;

        protected virtual void OnFinalized(EventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            if (Finalized != null)
                Finalized(this, e);
        }

        void Process_Finalized(object sender, EventArgs e)
        {
            this.OnFinalized(e);
        }
        #endregion

        #region Abort
        public virtual void Abort()
        {
            try
            {
                this.Process.BeginAbort();
            }
            catch (Exception ex)
            {
                HandleFault(ex);
            }
        }

        public event EventHandler Aborted;

        protected virtual void OnAborted(EventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            if (Aborted != null)
                Aborted(this, e);
        }

        void Process_Aborted(object sender, EventArgs e)
        {
            this.OnAborted(e);
        }
        #endregion

        #region Disconnect
        public void Disconnect()
        {
            try
            {
                this.Process.Disconnect();
            }
            catch (Exception ex)
            {
                HandleFault(ex);
            }
        }

        public event EventHandler Disconnected;

        protected virtual void OnDisconnected(EventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            this.IsConnected = false;

            if (Disconnected != null)
                Disconnected(this, e);
        }

        void Process_Disconnected(object sender, EventArgs e)
        {
            this.OnDisconnected(e);
        }
        #endregion

        #region RetrieveLog
        public List<LogEntity> RetrieveLogList()
        {
            try
            {
                return this.Process.RetrieveLogList();
            }
            catch (Exception ex)
            {
                HandleFault(ex);
            }
            return null;
        }

        public LogEntity RetrieveLastProcessLog()
        {
            try
            {
                return this.Process.RetrieveLastProcessLog();
            }
            catch (Exception ex)
            {
                HandleFault(ex);
            }
            return null;
        }
        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            if (this.Process != null)
            {
                this.Process.Dispose();
            }
        }

        #endregion
    }
}
